﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;

namespace Elentok.Common.Wpf.Dialogs
{
  /// <summary>
  /// The view model of the Select-Encoding dialog.
  /// </summary>
  public interface ISelectEncodingDialogViewModel
  {
    /// <summary>
    /// Gets or sets the selected encoding info.
    /// </summary>
    /// <value>The selected encoding info.</value>
    EncodingInfo SelectedEncodingInfo { get; set; }
    /// <summary>
    /// Gets or sets the selected encoding.
    /// </summary>
    /// <value>The selected encoding.</value>
    Encoding SelectedEncoding { get; set; }
    /// <summary>
    /// Gets all encoding infos.
    /// </summary>
    /// <value>All encoding infos.</value>
    ListCollectionView AllEncodingInfos { get; }
    /// <summary>
    /// Gets or sets the filter text.
    /// </summary>
    /// <value>The filter text.</value>
    string FilterText { get; set; }
    /// <summary>
    /// Gets a value indicating whether the ok button is enabled
    /// </summary>
    /// <value>
    /// 	<c>true</c> if the ok button is enabled; otherwise, <c>false</c>.
    /// </value>
    bool IsOkEnabled { get; }
  }

  /// <summary>
  /// An implementation of the <see cref="ISelectEncodingDialogViewModel"/>.
  /// </summary>
  public class SelectEncodingDialogViewModel : ViewModelBase, ISelectEncodingDialogViewModel
  {
    #region Private Members

    private Encoding selectedEncoding;
    private EncodingInfo selectedEncodingInfo;
    private string filterText;
    private EncodingInfo[] allEncodingInfos;

    #endregion

    /// <summary>
    /// Initializes a new instance of the <see cref="SelectEncodingDialogViewModel"/> class.
    /// </summary>
    public SelectEncodingDialogViewModel()
    {
      this.allEncodingInfos = Encoding.GetEncodings();
      this.AllEncodingInfos = new ListCollectionView(this.allEncodingInfos);
      this.AllEncodingInfos.Filter = AllEncodingInfos_Filter;
    }

    private bool AllEncodingInfos_Filter(object encodingInfoObject)
    {
      if (string.IsNullOrEmpty(this.filterText))
        return true;

      EncodingInfo encodingInfo = (EncodingInfo)encodingInfoObject;

      string lowercaseFilterText = this.filterText.ToLowerInvariant();

      if (encodingInfo.DisplayName.ToLowerInvariant().Contains(lowercaseFilterText))
        return true;

      if (encodingInfo.CodePage.ToString().Contains(lowercaseFilterText))
        return true;

      return false;
    }

    #region ISelectEncodingDialogViewModel Members

    /// <summary>
    /// Gets all encoding infos.
    /// </summary>
    /// <value>All encoding infos.</value>
    public ListCollectionView AllEncodingInfos { get; private set; }

    /// <summary>
    /// Gets or sets the filter text.
    /// </summary>
    /// <value>The filter text.</value>
    public string FilterText
    {
      get
      {
        return this.filterText;
      }
      set
      {
        if (this.filterText == value)
          return;

        this.filterText = value;
        AllEncodingInfos.Refresh();
        OnPropertyChanged("FilterText");
      }
    }

    /// <summary>
    /// Gets or sets the selected encoding.
    /// </summary>
    /// <value>The selected encoding.</value>
    public Encoding SelectedEncoding
    {
      get
      {
        return this.selectedEncoding;
      }
      set
      {
        if (this.selectedEncoding == value)
          return;

        this.selectedEncoding = value;

        if (value == null)
          this.SelectedEncodingInfo = null;
        else
          this.SelectedEncodingInfo =
            this.allEncodingInfos.FirstOrDefault(encInfo => encInfo.Name == value.WebName);

        OnPropertyChanged("SelectedEncoding");
        OnPropertyChanged("IsOkEnabled");
      }
    }

    /// <summary>
    /// Gets or sets the selected encoding info.
    /// </summary>
    /// <value>The selected encoding info.</value>
    public EncodingInfo SelectedEncodingInfo
    {
      get
      {
        return this.selectedEncodingInfo;
      }
      set
      {
        if (this.selectedEncodingInfo == value)
          return;

        this.selectedEncodingInfo = value;
        
        if (value == null)
          this.SelectedEncoding = null;
        else
          this.SelectedEncoding = value.GetEncoding();

        OnPropertyChanged("SelectedEncodingInfo");
      }
    }

    /// <summary>
    /// Gets a value indicating whether the ok button is enabled
    /// </summary>
    /// <value>
    /// 	<c>true</c> if the ok button is enabled; otherwise, <c>false</c>.
    /// </value>
    public bool IsOkEnabled
    {
      get
      {
        return this.SelectedEncoding != null;
      }
    }
    
    #endregion
  }
}
